"""
学生信息管理系统 - 学生类 (数据模型层)

📚 教学目标：
1. 理解面向对象编程的基本概念
2. 学习类的设计和实现
3. 掌握数据验证的重要性
4. 了解魔术方法的使用

🎯 本模块在项目中的作用：
- 定义学生数据结构
- 提供数据验证功能
- 实现数据格式转换
- 是整个系统的基础数据模型

⭐ 学习顺序：【第1步】- 建议首先学习此模块
"""

class Student:
    def __init__(self, student_id, name, age, gender, major, class_name, phone="", email=""):
        """
        初始化学生对象
        
        🎓 教学要点：
        - __init__ 是Python的构造函数（魔术方法）
        - self 表示实例本身，是Python面向对象的重要概念
        - 可以设置默认参数（如 phone="", email=""）
        - 实例属性的定义和赋值
        
        参数说明：
        :param student_id: 学号（必填，字符串类型）
        :param name: 姓名（必填，字符串类型）
        :param age: 年龄（必填，整数类型）
        :param gender: 性别（必填，字符串类型：'男'或'女'）
        :param major: 专业（必填，字符串类型）
        :param class_name: 班级（必填，字符串类型）
        :param phone: 电话（可选，字符串类型，默认为空）
        :param email: 邮箱（可选，字符串类型，默认为空）
        """
        # 💡 实例属性：每个学生对象都有自己独立的属性值
        self.student_id = student_id  # 学号 - 唯一标识符
        self.name = name  # 姓名
        self.age = age  # 年龄
        self.gender = gender  # 性别
        self.major = major  # 专业
        self.class_name = class_name  # 班级
        self.phone = phone  # 电话（可选）
        self.email = email  # 邮箱（可选）

    def __str__(self):
        """
        返回学生信息的字符串表示
        
        🎓 教学要点：
        - __str__ 是Python的魔术方法，定义对象的字符串表示
        - 当使用 print(student) 或 str(student) 时会调用此方法
        - f-string（格式化字符串）的使用，Python 3.6+的新特性
        - 字符串拼接和格式化的方法
        
        💡 应用场景：
        - 调试时查看对象内容
        - 在控制台输出对象信息
        - 日志记录
        """
        return f"学号: {self.student_id}, 姓名: {self.name}, 年龄: {self.age}, " \
               f"性别: {self.gender}, 专业: {self.major}, 班级: {self.class_name}, " \
               f"电话: {self.phone}, 邮箱: {self.email}"

    def to_dict(self):
        """
        将学生对象转换为字典
        
        🎓 教学要点：
        - 数据格式转换的重要性
        - 字典是Python中重要的数据结构
        - JSON序列化的准备工作（字典可以直接转为JSON）
        - 数据传输和存储的标准格式
        
        💡 应用场景：
        - 数据序列化（转换为JSON、XML等格式）
        - 与Web API交互
        - 数据导出功能
        
        :return: 包含学生信息的字典
        """
        return {
            'student_id': self.student_id,
            'name': self.name,
            'age': self.age,
            'gender': self.gender,
            'major': self.major,
            'class_name': self.class_name,
            'phone': self.phone,
            'email': self.email
        }

    @classmethod
    def from_tuple(cls, data_tuple):
        """
        从数据库查询结果元组创建学生对象
        
        🎓 教学要点：
        - @classmethod 装饰器的使用和意义
        - cls 参数表示类本身，而不是实例
        - 工厂方法模式的应用
        - 数据库查询结果通常是元组格式
        - 类方法 vs 实例方法 vs 静态方法的区别
        
        💡 设计模式：工厂方法
        - 提供多种创建对象的方式
        - 封装对象创建的复杂逻辑
        - 提高代码的可读性和可维护性
        
        :param data_tuple: 数据库查询结果元组
                          格式：(id, student_id, name, age, gender, major, class_name, phone, email, created_time)
        :return: Student对象实例，如果数据不完整则返回None
        """
        # 💡 防御性编程：检查数据完整性
        # data_tuple: (id, student_id, name, age, gender, major, class_name, phone, email, created_time)
        if len(data_tuple) >= 9:
            return cls(  # 💡 使用cls()创建新实例，等同于Student()但更灵活
                student_id=data_tuple[1],  # 跳过id（索引0），从student_id开始
                name=data_tuple[2],
                age=data_tuple[3],
                gender=data_tuple[4],
                major=data_tuple[5],
                class_name=data_tuple[6],
                phone=data_tuple[7] or "",  # 💡 处理None值，转换为空字符串
                email=data_tuple[8] or ""
            )
        return None  # 💡 数据不完整时返回None，调用方需要检查返回值


# 示例用法
if __name__ == "__main__":
    # 创建一个学生对象
    student = Student(
        student_id="2025001",
        name="张三",
        age=20,
        gender="男",
        major="计算机应用技术",
        class_name="计算机1班",
        phone="138020250011",
        email="example@example.com",
    )
    # 打印学生信息
    print(student)  # 输出学生信息

    print(len(student.__str__()))
    # 将学生对象转换为字典
    student_dict = student.to_dict()
    # print(student_dict)  # 输出字典格式的学生信息
    # 从元组创建学生对象
